﻿namespace FFF.Test
{
    using System;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    using Abp.Application.Services;
    using Abp.AspNetCore.Runtime.Cache;
    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.IdentityModel.Tokens;
    using FFF.Test.Filters;
    using FFF.Test.Util.Consts;
    using FFF.Test.Util.Web;
    using Swashbuckle.AspNetCore.Swagger;
    using Swashbuckle.AspNetCore.SwaggerGen;
    using Swashbuckle.AspNetCore.SwaggerUI;

    /// <summary>
    /// 配置文档生成
    /// </summary>
    public static class DocConfigurer
    {
        /// <summary>
        /// 配置文档生成
        /// </summary>
        /// <param name="services">程序的服务对象</param>
        /// <param name="configuration">程序的配置对象</param>
        /// <param name="env">环境节点</param>
        public static void ConfigureServices(IServiceCollection services, IConfiguration configuration, IHostingEnvironment env)
        {
            if (!env.IsProduction())
            {
                services.AddSwaggerGen(options =>
                {
                    options.SwaggerDoc("Demo", new Info { Title = "Demoapi" });
                    options.SwaggerDoc("FW", new Info { Title = "框架API" });
                    options.SwaggerDoc("WX", new Info { Title = "WX" });
                    options.DocInclusionPredicate((docName, apiDesc) =>
                    {
                        if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo))
                        {
                            return false;
                        }

                        System.Collections.Generic.IEnumerable<string> versions = methodInfo.DeclaringType
                            .GetCustomAttributes(true)
                            .OfType<YdmApiVersionAttribute>()
                            .Select(attr => attr.Version);

                        return versions.Any(v => $"{v.ToString()}" == docName);
                    });

                    // Define the BearerAuth scheme that's in use
                    options.AddSecurityDefinition("bearerAuth", new ApiKeyScheme()
                    {
                        Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                        Name = "Authorization",
                        In = "header",
                        Type = "apiKey"
                    });

                    // Assign scope requirements to operations based on AuthorizeAttribute
                    options.OperationFilter<SecurityRequirementsOperationFilter>();

                    //string xmlCommentsPath = Path.Combine(Server.BinPath, "FFF.Test.Application.xml");
                    //options.IncludeXmlComments(xmlCommentsPath, true);

                    //string xmlCommentsPath = Path.Combine(Server.BinPath, "FFF.Test.Entity.xml");
                    //options.IncludeXmlComments(xmlCommentsPath, true);
                });
            }

        }

        /// <summary>
        /// 文档的配置
        /// </summary>
        /// <param name="app">app环境</param>
        /// <param name="env">env的环境</param>
        public static void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (!env.IsProduction())
            {
                app.UseMiddleware<SwaggerCacheMiddleware>(CacheAppConsts.WebSiteCache);
                app.UseSwagger(c =>
                {
                    c.PreSerializeFilters.Add((swaggerDoc, httpReq) => swaggerDoc.Host = httpReq.Host.Value);
                    c.RouteTemplate = "api/doc/{documentName}/swagger.json";
                });
                app.UseSwaggerUI(options =>
                {
                    options.RoutePrefix = "api/doc";
                    options.SwaggerEndpoint("/api/doc/Demo/swagger.json", "Demo");
                    options.SwaggerEndpoint("/api/doc/FW/swagger.json", "FW");
                    options.SwaggerEndpoint("/api/doc/WX/swagger.json", "WX");
                    options.IndexStream = () => Assembly.GetExecutingAssembly()
                    .GetManifestResourceStream("FFF.Test.wwwroot.swagger.ui.Index.html");
                    options.EnableFilter();
                    options.DocExpansion(DocExpansion.None);
                    options.DefaultModelsExpandDepth(-1);
                });
                HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize();
            }

        }
    }
}
